/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */

package com.huawei.demo;

import com.huaweicloud.sdk.core.auth.BasicCredentials;
import com.huaweicloud.sdk.core.http.HttpConfig;
import com.huaweicloud.sdk.ugo.v1.UgoClient;
import com.huaweicloud.sdk.ugo.v1.model.CommitSyntaxConversionRequest;
import com.huaweicloud.sdk.ugo.v1.model.CommitVerificationRequest;
import com.huaweicloud.sdk.ugo.v1.model.CreateMigrationProject;
import com.huaweicloud.sdk.ugo.v1.model.CreateMigrationProjectRequest;
import com.huaweicloud.sdk.ugo.v1.model.DeleteMigrationProjectRequest;
import com.huaweicloud.sdk.ugo.v1.model.DownloadFailureReportRequest;
import com.huaweicloud.sdk.ugo.v1.model.ListMigrationProjectsRequest;
import com.huaweicloud.sdk.ugo.v1.model.ListMigrationProjectsResponse;
import com.huaweicloud.sdk.ugo.v1.model.ListPermissionCheckResultRequest;
import com.huaweicloud.sdk.ugo.v1.model.ListSyntaxConversionProgressRequest;
import com.huaweicloud.sdk.ugo.v1.model.ListSyntaxConversionProgressResponse;
import com.huaweicloud.sdk.ugo.v1.model.ListVerificationProgressRequest;
import com.huaweicloud.sdk.ugo.v1.model.ListVerificationProgressResponse;
import com.huaweicloud.sdk.ugo.v1.model.MigrationProject;
import com.huaweicloud.sdk.ugo.v1.model.ShowMigrationProjectDetailRequest;
import com.huaweicloud.sdk.ugo.v1.model.ShowMigrationProjectStatusRequest;
import com.huaweicloud.sdk.ugo.v1.model.ShowMigrationProjectStatusResponse;
import com.huaweicloud.sdk.ugo.v1.model.TargetDBInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * 数据库和应用迁移 UGO的示例代码：对象迁移
 *
 * @since 2022-08-20
 */
public class MigrationProjectDemo {

    private static final Logger logger = LoggerFactory.getLogger(MigrationProjectDemo.class);

    public static void main(String[] args) throws InterruptedException {

        UgoClient ugoClient = getUgoClient();

        String migrationProjectName = "<YOUR MIGRATION PROJECT NAME>";
        String targetDBInstanceId = "<YOUR TARGET DATABASE INSTANCE ID>";
        String targetDBUserName = "<YOUR TARGET DATABASE USERNAME>";
        String targetDBPassword = "<YOUR TARGET DATABASE PASSWORD>";
        String targetDBServiceName = "<YOUR TARGET DATABASE SERVICE NAME>";
        Integer evaluationProjectId = 187;

        TargetDBInfo targetDBInfo = new TargetDBInfo();
        targetDBInfo.setInstanceId(targetDBInstanceId);
        targetDBInfo.setUserName(targetDBUserName);
        targetDBInfo.setPassword(targetDBPassword);
        targetDBInfo.setServiceName(targetDBServiceName);

        // Step 1: Create ugo migration project.
        createMigrationProject(ugoClient, migrationProjectName, evaluationProjectId, targetDBInfo);

        // Step 2: Get migration project list.
        String migrationProjectId = getMigrationProjectId(ugoClient, migrationProjectName);

        // Step 3: Check migration project status.
        checkMigrationProjectStatus(ugoClient, migrationProjectId);

        // Step 4: Get target db permission check result.
        ListPermissionCheckResultRequest listPermissionCheckResultRequest = new ListPermissionCheckResultRequest();
        listPermissionCheckResultRequest.setMigrationProjectId(migrationProjectId);
        ugoClient.listPermissionCheckResult(listPermissionCheckResultRequest);

        // Step 5: Get migration project detail.
        ShowMigrationProjectDetailRequest showMigrationProjectDetailRequest = new ShowMigrationProjectDetailRequest();
        showMigrationProjectDetailRequest.setMigrationProjectId(migrationProjectId);
        ugoClient.showMigrationProjectDetail(showMigrationProjectDetailRequest);

        // Step 6: Start to syntax conversion.
        CommitSyntaxConversionRequest commitSyntaxConversionRequest = new CommitSyntaxConversionRequest();
        commitSyntaxConversionRequest.setMigrationProjectId(migrationProjectId);
        ugoClient.commitSyntaxConversion(commitSyntaxConversionRequest);

        // Step 7: Check syntax conversion progress.
        checkSyntaxConversionProgress(ugoClient, migrationProjectId);

        // Step 8: Start to verification.
        CommitVerificationRequest commitVerificationRequest = new CommitVerificationRequest();
        commitVerificationRequest.setMigrationProjectId(migrationProjectId);
        ugoClient.commitVerification(commitVerificationRequest);

        // Step 9: Check verification progress.
        checkVerificationProgress(ugoClient, migrationProjectId);

        // Step 10: Download failure report.
        DownloadFailureReportRequest downloadFailureReportRequest = new DownloadFailureReportRequest();
        downloadFailureReportRequest.setMigrationProjectId(migrationProjectId);
        ugoClient.downloadFailureReport(downloadFailureReportRequest);

        // Step 11: Delete migration project.
        DeleteMigrationProjectRequest deleteMigrationProjectRequest = new DeleteMigrationProjectRequest();
        deleteMigrationProjectRequest.setMigrationProjectId(migrationProjectId);
        ugoClient.deleteMigrationProject(deleteMigrationProjectRequest);

    }

    private static UgoClient getUgoClient() {
        String ak = "<YOUR AK>";
        String sk = "<YOUR SK>";
        String endpoint = "<YOUR ENDPOINT>";
        String projectId = "<YOUR PROJECTID>";

        // Http Configuration for client
        HttpConfig config = HttpConfig.getDefaultHttpConfig();
        config.withIgnoreSSLVerification(true);

        // Create the authentication
        BasicCredentials auth = new BasicCredentials()
                .withAk(ak)
                .withSk(sk)
                .withProjectId(projectId);

        // Create UgoClient instance
        return UgoClient.newBuilder()
                .withHttpConfig(config)
                .withCredential(auth)
                .withEndpoint(endpoint)
                .build();
    }

    private static void createMigrationProject(UgoClient ugoClient, String migrationProjectName, Integer evaluationProjectId, TargetDBInfo targetDBInfo) {
        CreateMigrationProjectRequest createMigrationProjectRequest = new CreateMigrationProjectRequest();
        CreateMigrationProject createMigrationProjectBody = new CreateMigrationProject();
        createMigrationProjectBody.setEvaluationProjectId(evaluationProjectId);
        createMigrationProjectBody.setMigrationProjectName(migrationProjectName);
        createMigrationProjectBody.setTargetDbInfo(targetDBInfo);
        createMigrationProjectBody.setOpenGaussConfig(null);
        createMigrationProjectRequest.setBody(createMigrationProjectBody);
        ugoClient.createMigrationProject(createMigrationProjectRequest);
    }

    private static void checkMigrationProjectStatus(UgoClient ugoClient, String migrationProjectId) throws InterruptedException {
        ShowMigrationProjectStatusRequest showMigrationProjectStatusRequest = new ShowMigrationProjectStatusRequest();
        showMigrationProjectStatusRequest.setMigrationProjectId(migrationProjectId);
        while (true) {
            ShowMigrationProjectStatusResponse showMigrationProjectStatusResponse
                    = ugoClient.showMigrationProjectStatus(showMigrationProjectStatusRequest);
            String readyStatus = ShowMigrationProjectStatusResponse.MigrationProjectStatusEnum.READY.getValue();
            ShowMigrationProjectStatusResponse.MigrationProjectStatusEnum migrationProjectStatus
                    = showMigrationProjectStatusResponse.getMigrationProjectStatus();
            ShowMigrationProjectStatusResponse.PermissionCheckStatusEnum permissionCheckStatus
                    = showMigrationProjectStatusResponse.getPermissionCheckStatus();
            if (!readyStatus.equals(migrationProjectStatus.getValue())) {
                logger.info("migration project is not ready, permission check status: {}", permissionCheckStatus.getValue());
                Thread.sleep(2000);
                continue;
            }
            logger.info("migration project is ready");
            break;
        }
    }

    private static String getMigrationProjectId(UgoClient ugoClient, String migrationProjectName) throws InterruptedException {
        ListMigrationProjectsRequest listMigrationProjectsRequest = new ListMigrationProjectsRequest();
        Integer migrationProjectId = null;
        OUT:
        while (true) {
            ListMigrationProjectsResponse listMigrationProjectsResponse = ugoClient.listMigrationProjects(listMigrationProjectsRequest);
            List<MigrationProject> migrationProjects = listMigrationProjectsResponse.getMigrationProjects();
            for (MigrationProject project : migrationProjects) {
                if (!migrationProjectName.equals(project.getMigrationProjectName())) {
                    Thread.sleep(2000);
                    continue;
                }
                logger.info("create ugo migration project success.");
                migrationProjectId = project.getMigrationProjectId();
                break OUT;
            }
        }
        return Integer.toString(migrationProjectId);
    }

    private static void checkSyntaxConversionProgress(UgoClient ugoClient, String migrationProjectId) throws InterruptedException {
        ListSyntaxConversionProgressRequest listSyntaxConversionProgressRequest = new ListSyntaxConversionProgressRequest();
        listSyntaxConversionProgressRequest.setMigrationProjectId(migrationProjectId);
        while (true) {
            ListSyntaxConversionProgressResponse listSyntaxConversionProgressResponse
                    = ugoClient.listSyntaxConversionProgress(listSyntaxConversionProgressRequest);
            Integer completedObjectsCount = listSyntaxConversionProgressResponse.getCompletedObjectsCount();
            Integer totalObjectsCount = listSyntaxConversionProgressResponse.getTotalObjectsCount();
            if (completedObjectsCount.equals(totalObjectsCount)) {
                logger.info("syntax conversion success.");
                break;
            }
            logger.info("syntax conversion in progress, total:{}, completed:{}.", totalObjectsCount, completedObjectsCount);
            Thread.sleep(5000);
        }
    }

    private static void checkVerificationProgress(UgoClient ugoClient, String migrationProjectId) throws InterruptedException {
        ListVerificationProgressRequest listVerificationProgressRequest = new ListVerificationProgressRequest();
        listVerificationProgressRequest.setMigrationProjectId(migrationProjectId);
        while (true) {
            ListVerificationProgressResponse listVerificationProgressResponse
                    = ugoClient.listVerificationProgress(listVerificationProgressRequest);
            Integer completedObjectsCount = listVerificationProgressResponse.getCompletedObjectsCount();
            Integer totalObjectsCount = listVerificationProgressResponse.getTotalObjectsCount();
            if (completedObjectsCount.equals(totalObjectsCount)) {
                logger.info("verification success.");
                break;
            }
            logger.info("verification in progress, total:{}, completed:{}.", totalObjectsCount, completedObjectsCount);
            Thread.sleep(5000);
        }
    }

}
